﻿

////////////////////////////////////////////////////////////////////////////////
#ifndef __ASIO_PLUSPLUS_INCLUDED_H_
#define __ASIO_PLUSPLUS_INCLUDED_H_
////////////////////////////////////////////////////////////////////////////////
#ifndef ASIO_PLUS_VERSION
#define ASIO_PLUS_VERSION     0x01000005
#endif
#ifndef ASIO_PLUS_VERSION_STR
#define ASIO_PLUS_VERSION_STR "1.0.0.5"
#endif
#ifndef ASIO_IO_WINDOW_SIZE
#define ASIO_IO_WINDOW_SIZE   8192
#endif
#ifndef ASIO_RESULT_OK
#define ASIO_RESULT_OK        0
#endif
#ifndef ASIO_MAX_WSP_PACKET
#define ASIO_MAX_WSP_PACKET   ASIO_IO_WINDOW_SIZE
#endif
#ifndef ASIO_STANDALONE
#define ASIO_STANDALONE       //独立使用 ASIO 库
#endif
#ifndef ASIO_HAS_STD_CHRONO
#define ASIO_HAS_STD_CHRONO   //独立使用 ASIO 库
#endif
////////////////////////////////////////////////////////////////////////////////
#include <memory>
#include <list>
#include <thread>
#include <functional>
#include <condition_variable>
#include <mutex>
#include <atomic>
#include <asio.hpp>
////////////////////////////////////////////////////////////////////////////////
#include <asio++/stringc.h>
#include <asio++/mutex.h>
#include <asio++/conf.h>
#include <asio++/rrdata.h>
#include <asio++/rc4.h>
#include <asio++/hashsolt.h>
#include <asio++/circular_buffer.h>
////////////////////////////////////////////////////////////////////////////////
#if defined(ASIO_ENABLE_ZENCODE)
#include <asio++/compress.h>
#endif
////////////////////////////////////////////////////////////////////////////////
#if defined(ASIO_ENABLE_OPENSSL)
#include <asio/ssl.hpp>
////////////////////////////////////////////////////////////////////////////////
namespace ssl {
////////////////////////////////////////////////////////////////////////////////
class context : public asio::ssl::context {
public:
    inline context(const char *cert, const char *key)
        : asio::ssl::context(ssl::context::sslv23){
        load(cert, key);
    }
    inline context()
        : asio::ssl::context(ssl::context::sslv23) {
    }
    inline void load(const char *cert, const char *key){
        long options = default_workarounds;
        options |= no_sslv2;
        options |= single_dh_use;
        set_options(options);
        use_certificate_chain_file(cert);
        use_private_key_file(key, ssl::context::pem);
    }
};
////////////////////////////////////////////////////////////////////////////////
} //End of namespace ssl.
////////////////////////////////////////////////////////////////////////////////
#endif
////////////////////////////////////////////////////////////////////////////////
template<typename _Ty>
class enable_shared_from_this
    : public std::enable_shared_from_this<_Ty>{
protected:
    inline void save_exception(const std::exception &e){
        FILE *fp = fopen("./~exception.log", "a+");
        if (fp) {
            std::string log;
            log += "Exception occurred: ";
            log += e.what();
            fwrite(log.c_str(), 1, log.size(), fp);
            fclose(fp);
        }
    }
};
////////////////////////////////////////////////////////////////////////////////
namespace ip{
    namespace tcp{
        class connector; //TCP 连接器
        class listener;  //TCP 监听器
    }
}
////////////////////////////////////////////////////////////////////////////////
//异步执行处理函数，当前函数立即返回
////////////////////////////////////////////////////////////////////////////////
static asio::io_service& __Afx_get_service(){
    static bool is_runing = false;
    static asio::io_service ios;
    static asio::io_service::work work(ios);
    if (!is_runing){
        is_runing = true;
        for (int i = 0; i < 4; i++){
            is_runing = true;
            std::thread([](){ios.run();}).detach();
        }
    }
    return ios;
}
////////////////////////////////////////////////////////////////////////////////
static asio::io_service::strand& __Afx_get_strand(){
    static asio::io_service& ios = __Afx_get_service();
    static asio::io_service::strand strand(ios);
    return strand;
}
////////////////////////////////////////////////////////////////////////////////
template<typename Handler>
inline void async_invoke(Handler handler, bool in_order = false){
    static asio::io_service& ios = __Afx_get_service();
    static asio::io_service::strand& strand = __Afx_get_strand();
    in_order ? strand.post(handler) : ios.post(handler);
}
////////////////////////////////////////////////////////////////////////////////
namespace io{
////////////////////////////////////////////////////////////////////////////////
//核心IO类
////////////////////////////////////////////////////////////////////////////////
class service
    : public enable_shared_from_this<service>{
    inline service()
        : m_idletime(0)
        , m_work(new asio::io_service::work(m_ios)){
    }
    inline explicit service(size_t);
    friend class ip::tcp::listener;
    friend class ip::tcp::connector;
public:
    template<typename Handler>
    inline void dispatch(Handler handler){
        m_ios.dispatch(handler);
    }
    template<typename Handler>
    inline void post(Handler handler){
        m_ios.post(handler);
    }
    template<typename Handler>
    inline size_t run(Handler handler, size_t timeout){
        begin_period(1);
        size_t now, delta, total = 0;
        size_t last = time_get_time();
        while (!stopped()){
            now = time_get_time();
            delta = now - last;
            if (delta >= timeout){
                last = now;
                handler((int)delta);
            }
            total += wait_poll_one();
        }
        end_period(1);
        return total;
    }
public:
    typedef std::shared_ptr<service> value_type;
    inline static value_type create(){
        return value_type(new service());
    }
    inline operator asio::io_service&(){
        return m_ios;
    }
    inline bool stopped() const{
        return m_ios.stopped();
    }
    inline void stop(){
        m_ios.post(
            std::bind(&asio::io_service::stop, &m_ios)
        );
    }
    inline size_t get_idle_time() const{
        return m_idletime;
    }
    inline void reset(){
        m_ios.reset();
        if (m_work){
            return;
        }
        m_work.reset(
            new asio::io_service::work(m_ios)
        );
    }
    size_t run(){
        size_t total = 0;
        asio::error_code ec;
        begin_period(1);
        while (!stopped()){
            total += wait_poll_one();
        }
        end_period(1);
        return total;
    }
    inline size_t run_one(){
        asio::error_code ec;
        return m_ios.run_one(ec);
    }
    inline size_t poll(){
        asio::error_code ec;
        return m_ios.poll(ec);
    }
    inline size_t poll_one(){
        asio::error_code ec;
        return m_ios.poll_one(ec);
    }
private:
    size_t m_idletime;
    asio::io_service m_ios;
    std::shared_ptr<asio::io_service::work> m_work;
private:
    size_t wait_poll_one(){
        asio::error_code ec;
        size_t result = m_ios.poll_one(ec);
        if (result == 0){
            const int timeout = 1;
            m_idletime += timeout;
            std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
        }
        return result;
    }
private:
    static std::mutex& get_id_mutex(){
        static std::mutex g_mutex;
        return g_mutex;
    }
    static std::list<int>& get_id_list(){
        static std::list<int> g_list;
        return g_list;
    }
    static int pop_next_id(){
        static unsigned int gid = 0;
        std::unique_lock<std::mutex> lock(get_id_mutex());
        if (gid < 0xfffff){
            return ++gid;
        }
        int id = 0;
        if (get_id_list().size()){
            id = get_id_list().front();
            get_id_list().pop_front();
        }
        return id;
    }
    static void push_idle_id(int id){
        if (id <= 0 || id > 0xfffff){
            return;
        }
        std::unique_lock<std::mutex> lock(get_id_mutex());
        get_id_list().push_back(id);
    }
};
////////////////////////////////////////////////////////////////////////////////
} //End of namespace io
////////////////////////////////////////////////////////////////////////////////
namespace ip{
////////////////////////////////////////////////////////////////////////////////
namespace tcp{
////////////////////////////////////////////////////////////////////////////////
enum event_type{io_read = 1, io_write = 2, io_connect = 3};
enum style_type{tcpsocket = 0, websocket = 1};
enum rwset_type{r_buffer = 0, w_buffer = 1};
////////////////////////////////////////////////////////////////////////////////
typedef struct __inet_event{
    event_type  type;    //事件类型
    size_t      bytes;   //传输的字节数
    const char* buffer;  //数据指针
} inet_event;
////////////////////////////////////////////////////////////////////////////////
class iostream {
    io::service::value_type m_ios;
    asio::ip::tcp::socket   m_socket;
#if defined(ASIO_ENABLE_OPENSSL)
    typedef asio::ssl::stream<asio::ip::tcp::socket> ssl_socket;
#endif
public:
    inline iostream(io::service::value_type ios)
        : m_ios(ios)
        , m_socket(*ios)
        , m_closed(false)
    {}
#if defined(ASIO_ENABLE_OPENSSL)
    inline iostream(io::service::value_type ios, ssl::context &ssl)
        : m_ios(ios)
        , m_socket(*ios)
        , m_closed(false)
        , m_stream(new ssl_socket(*ios, ssl)){
    }
#endif
    inline bool is_open() const{
        return !m_closed;
    }
    inline size_t receive(char *buffer, size_t size){
        size_t recved = 0;
        asio::error_code ec;
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            recved = m_stream->read_some(
                asio::buffer(buffer, size), ec
            );
            return recved;
        }
#endif
        recved = m_socket.receive(
            asio::buffer(buffer, size), 0, ec
        );
        return recved;
    }
    inline size_t send(const std::string &data){
        size_t sent = 0;
        asio::error_code ec;
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            sent = m_stream->write_some(
                asio::buffer(data.c_str(), data.size()), ec
            );
            return sent;
        }
#endif
        sent = m_socket.send(
            asio::buffer(data.c_str(), data.size()), 0, ec
        );
        return sent;
    }
    inline bool is_openssl() const{
#if defined(ASIO_ENABLE_OPENSSL)
        return (m_stream != 0);
#else
        return false;
#endif
    }
    asio::ip::tcp::socket::lowest_layer_type& lowest_layer(){
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            return m_stream->lowest_layer();
        }
#endif
        return m_socket.lowest_layer();
    }
    inline void close(){
        if (!is_open()){
            return;
        }
        asio::error_code ec;
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            m_stream->shutdown(ec);
        }
#endif
        m_closed = true;
        m_socket.close(ec);
    }
#if defined(ASIO_ENABLE_OPENSSL)
    template<typename Handler>
    inline void async_handshake(Handler handler){
        if (!is_open()){
            return;
        }
        if (m_stream){
            m_stream->async_handshake(
                asio::ssl::stream_base::server, handler
            );
        }
    }
#endif
    template<typename Buffer, typename Handler>
    inline void async_send(Buffer buffer, Handler handler){
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            m_stream->async_write_some(buffer, handler);
            return;
        }
#endif
        m_socket.async_send(buffer, handler);
    }
    template<typename Buffer, typename Handler>
    inline void async_receive(Buffer buffer, Handler handler){
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_stream){
            m_stream->async_read_some(buffer, handler);
            return;
        }
#endif
        m_socket.async_receive(buffer, handler);
    }
private:
    bool m_closed;
#if defined(ASIO_ENABLE_OPENSSL)
    std::shared_ptr<
        asio::ssl::stream<asio::ip::tcp::socket>
    > m_stream;
#endif
};
////////////////////////////////////////////////////////////////////////////////
//网络连接类
////////////////////////////////////////////////////////////////////////////////
class connector
    : public enable_shared_from_this<connector>{
    friend class listener;
public:
    typedef std::shared_ptr<
        connector
    > value_type;
public:
    //创建一个共享的 connector 实例指针
    static value_type create(io::service::value_type ios){
        value_type s(new connector(ios));
        if (s && s->id() == 0)
            s.reset();
        return s;
    }
#if defined(ASIO_ENABLE_OPENSSL)
    //创建一个共享的 connector 实例指针(支持 SSL 通道)
    static value_type create(io::service::value_type ios, ssl::context &ctx) {
        value_type s(new connector(ios, ctx));
        if (s && s->id() == 0)
            s.reset();
        return s;
    }
#endif
    //获取与 connector 关联的 io service 对象指针
    inline io::service::value_type get_io_service() const{
        return m_ios;
    }
    //设置关心的网络事件，默认只响应 io_read 事件
    inline bool set_events(int option){
        int mask = std::min<int>(
            option, io_read | io_write
            );
        if (mask != option)
            return false;
        return (m_events = option), true;
    }
    //获得 connector 响应的网络事件
    inline int get_events() const{
        return m_events;
    }
    //设置 connector 上下文指针
    inline void set_context(const void *context){
        m_context = context;
    }
    //获取 connector 上下文指针
    inline const void* get_context() const{
        return m_context;
    }
    //设置 connector 的 nagle 算法
    inline void set_nagle(bool enable){
        asio::ip::tcp::no_delay opt(!enable);
        m_socket.lowest_layer().set_option(opt);
    }
    //获取 connector 是否开启了 nagle 算法
    inline bool get_nagle(){
        asio::ip::tcp::no_delay opt;
        m_socket.lowest_layer().get_option(opt);
        return !opt.value();
    }
    //设置 connector 底层的读写缓冲区大小
    inline void buffer_size(rwset_type type, size_t size){
        if (type == r_buffer){
            m_socket.lowest_layer().set_option(
                asio::socket_base::receive_buffer_size((int)size)
            );
        } else if (type == w_buffer){
            m_socket.lowest_layer().set_option(
                asio::socket_base::send_buffer_size((int)size)
            );
        }
    }
    //获取 connector 底层的读写缓冲区大小
    inline size_t buffer_size(rwset_type type){
        if (type == r_buffer){
            asio::socket_base::receive_buffer_size opt;
            m_socket.lowest_layer().get_option(opt);
            return opt.value();
        }
        else if (type == w_buffer){
            asio::socket_base::send_buffer_size opt;
            m_socket.lowest_layer().get_option(opt);
            return opt.value();
        }
        return 0;
    }
    //获取 connector 的唯一标识符
    inline int id() const{
        return m_id;
    }
    //获取 connector 最后一次收到网络消息的时间
    inline time_t get_alivetime() const{
        return m_keepalive;
    }
    //获取 connector 的类型 ID
    inline style_type get_type() const{
        return m_type;
    }
    //获取 connector 对端的网络地址
    inline std::string get_peer_name() const{
        return m_peer.address().to_string();
    }
    //获取 connector 对端的网络端口
    inline unsigned short get_peer_port() const{
        return m_peer.port();
    }
    //判断 connector 当前是否处于 open 状态
    inline bool is_open() const{
        return m_socket.is_open();
    }
    //取消 socket 阻塞操作
    inline bool cancel() {
        asio::error_code ec;
        m_socket.lowest_layer().cancel(ec);
        return (ec.value() == 0);
    }
    //阻塞连接目标主机
    int connect(const char *name, unsigned short port){
        m_initiator = true;
        asio::error_code ec;
        m_socket.lowest_layer().connect(resolve(name, port), ec);
        if (!ec) {
            m_peer = m_socket.lowest_layer().remote_endpoint(ec);
        }
        return ec.value();
    }
    //在 connector 上发送数据(内部根据连接类型自动转换)
    void write(const std::string &data, int type = WSP_TYPE_TEXT){
        if (m_type != websocket){
            dispatch(data);
            return;
        }
        if (!m_wsp_ready){
            dispatch(data);
            return;
        }
        wsp_write(data, type);
    }
    //在 connector 上发送数据(内部根据连接类型自动转换)
    void write(const char *data, size_t size, int type = WSP_TYPE_TEXT){
        std::string packet;
        if (data && size){
            packet.append(data, size);
        }
        write(packet, type);
    }
    //获取与 connector 关联的 HTTP 请求头信息
    inline http::request& get_request(){
        return m_request;
    }
    //获取与 connector 关联的 HTTP 解析器
    inline http::request_parser& get_parser(){
        return m_req_parser;
    }
    //获取与 connector 关联的 Websocket 数据包解析器
    inline http::wsp_parser& get_wsp_parser(){
        return m_wsp_parser;
    }
    //设置 connector 允许的单个数据包最大字节长度
    inline void set_limit(int limit){
        m_limit = limit;
    }
    //设置 connector 完成 Websocket 握手标记
    inline void set_wsp_ready(){
        m_wsp_ready = true;
    }
    //设置 connector 的 cookie 值
    inline void set_cookie(const std::string &cookie){
        m_cookie = cookie;
    }
    //获取 connector 允许的单个数据包最大字节长度
    inline int get_limit() const{
        return m_limit;
    }
    //获取 connector 的 cookie 值
    inline std::string get_cookie() const{
        return m_cookie;
    }
    //判断 connector 是否为连接的主动发起方
    inline bool is_initiator() const{
        return m_initiator;
    }
    //判断 connector 是否已与 io service 建立绑定关系
    inline bool is_bind() const{
        return m_events > 0;
    }
    //判断 connector 是否开启了 SSL 通道
    inline bool is_openssl() const{
        return m_socket.is_openssl();
    }
    //把网络事件回调函数绑定到 connector 上
    template<typename Handler>
    int bind(Handler handler, bool keep_alive = false, style_type type = tcpsocket){
        asio::error_code ec;
        if (is_bind()){
            return ec.value();
        }
        m_peer = m_socket.lowest_layer().remote_endpoint(ec);
        if (ec){
            return ec.value();
        }
        m_socket.lowest_layer().set_option(
            asio::socket_base::keep_alive(keep_alive),
            ec
            );
        if (ec){
            return ec.value();
        }
        m_linger    = false;
        m_events    = io_read;
        m_type      = type;
        m_handler   = handler;
        m_keepalive = time(0);
        m_send.reserve(ASIO_IO_WINDOW_SIZE);

        if (!m_circular_buffer){
            m_circular_buffer = circular_buffer::create(ASIO_IO_WINDOW_SIZE);
            if (!m_circular_buffer)
                return asio::error::no_memory;
            m_circular_buffer->limit(0);
        }
        m_socket.async_receive(
            asio::buffer(m_recv, sizeof(m_recv)),
            std::bind(&connector::r_handler
                , shared_from_this()
                , std::placeholders::_1
                , std::placeholders::_2
                )
            );
        return ec.value();
    }
    //如果 connector 为 Websocket类型且为连接的主动发起方，
    //在连接成功后需要调用本函数进行 Websocket 握手
    inline bool handshake(const std::string &url){
        int state = 0;
        std::string method, host, port, uri("/");
        for (size_t i = 0; i < url.size(); i++){
            char c = tolower(url[i]);
            switch (state){
            case 0:
                if (c == ':') state = 1; else method += c;
                break;
            case 1:
                if (c != '/') return false;
                state = 2;
                break;
            case 2:
                if (c != '/') return false;
                state = 3;
                break;
            case 3:
                if (c == ':') state = 4; else if (c == '/') state = 5; else host += c;
                break;
            case 4:
                if (c == '/') state = 5; else port += c;
                break;
            case 5:
                uri += url[i];
                break;
            }
        }
        if (host.empty()){
            return false;
        }
        if (method == "ws"){
            port = (port == "80" ? "" : (":" + port));
        } else if (method == "wss"){
            port = (port == "443" ? "" : (":" + port));
        } else {
            return false;
        }
        unsigned int rv[4];
        for (int i = 0; i < 4; i++){
            rv[i] = rand_int();
        }
        char key[32];
        base64::encode((unsigned char*)rv, key, 16);
        m_request.method = "GET";
        m_request.url = uri;
        m_request.http_version_major = 1;
        m_request.http_version_minor = 1;
        m_request.add_header("Host", host + port);
        m_request.add_header("Upgrade", "websocket");
        m_request.add_header("Connection", "Upgrade");
        m_request.add_header("Sec-WebSocket-Key", key);
        m_request.add_header("Sec-WebSocket-Version", "13");
        m_request.add_header("Cache-Control", "no-cache");
        m_request.add_header("Pragma", "no-cache");
        m_request.add_header("User-Agent", "asio++ websocket");
        //发送握手请求
        std::string data = m_request.to_string();
        return (m_socket.send(data) == data.size());
    }
    //析构函数
    virtual ~connector(){
        m_socket.close();
        io::service::push_idle_id(m_id);
        console::log("%s is invoked.\r\n", __FUNCTION__);
    }
    //关闭 connector 的网络连接
    virtual void close(bool linger = false){
        get_io_service()->post(
            std::bind(&connector::sync_close
                , shared_from_this()
                , linger
                )
            );
    }
private:
    //默认构造函数
    inline connector(io::service::value_type ios)
        : m_context(0)
        , m_id(io::service::pop_next_id())
        , m_linger(false)
        , m_initiator(false)
        , m_events(0)
        , m_type(tcpsocket)
        , m_keepalive(time(0))
        , m_sendbegin(0)
        , m_ios(ios)
        , m_socket(ios)
        , m_wsp_ready(false){
        console::log("%s is invoked.\r\n", __FUNCTION__);
    }
#if defined(ASIO_ENABLE_OPENSSL)
    //默认构造函数
    inline connector(io::service::value_type ios, ssl::context &ctx)
        : m_context(0)
        , m_id(io::service::pop_next_id())
        , m_linger(false)
        , m_initiator(false)
        , m_events(0)
        , m_limit(ASIO_MAX_WSP_PACKET)
        , m_type(tcpsocket)
        , m_keepalive(time(0))
        , m_sendbegin(0)
        , m_ios(ios)
        , m_socket(ios, ctx)
        , m_wsp_ready(false){
        console::log("%s is invoked.\r\n", __FUNCTION__);
    }
#endif
    typedef std::function<void(
        int,                //错误号
        const inet_event&,  //事件数据指针
        value_type          //共享指针
    )> io_handler_callback;
private:
    const void*                 m_context;
    const int                   m_id;
    bool                        m_linger;
    bool                        m_initiator;
    int                         m_events;
    int                         m_limit;
    style_type                  m_type;
    char                        m_recv[ASIO_IO_WINDOW_SIZE];
    std::string                 m_send;
    std::string                 m_cookie;
    time_t                      m_keepalive;
    time_t                      m_sendbegin;
    asio::ip::tcp::endpoint     m_peer;
    io_handler_callback         m_handler;
    io::service::value_type     m_ios;
    asio::error_code            m_errno;
    iostream                    m_socket;
    http::request               m_request;
    http::request_parser        m_req_parser;
    bool                        m_wsp_ready;
    http::wsp_parser            m_wsp_parser;
    circular_buffer::value_type m_circular_buffer;
private:
    //通过域名/IP和端口来构造对端地址类型
    asio::ip::tcp::endpoint resolve(const char *name, int port){
        asio::ip::tcp::endpoint endpoint;
        if (!name){
            endpoint.port(port);
            return endpoint;
        }
        asio::error_code ec;
        asio::ip::address addr;
        addr = asio::ip::address::from_string(name, ec);
        if (!ec) {
            endpoint.address(addr);
        } else {
            auto ios = get_io_service();
            auto iter = asio::ip::tcp::resolver(*ios).resolve(
                asio::ip::tcp::resolver::query(name, ""), ec
                );
            asio::ip::tcp::resolver::iterator end;
            std::vector<asio::ip::tcp::endpoint> ip_array;
            for (;!ec && iter != end; iter++){
                ip_array.push_back(*iter);
            }
            size_t count = ip_array.size();
            if (count > 0){
                endpoint = ip_array[rand() % count];
            }
        }
        return (endpoint.port((unsigned short)port), endpoint);
    }
    //在 connector 上派发 TCP 数据
    void dispatch(const std::string &data){
        get_io_service()->post(
            std::bind(&connector::sync_write
                , shared_from_this()
                , data
                , false
            )
        );
    }
    //在 connector 上派发 Websocket 数据
    void wsp_write(const std::string &data, int type){
        std::string output(data);
        if (type == WSP_TYPE_TEXT){
            if (!is_utf8(data)){
                output = ctoutf8(data);
            }
        }
        //协议规定 client 必须要有 mask
        unsigned int mask = 0;
        if (is_initiator()) {
            mask = rand_int();
        }
        const char *begin = output.c_str();
        const char *end   = begin + output.size();
        do{
            std::string packet;
            begin = http::wsp_parser::pack(packet, begin, end, type, mask);
            dispatch(packet);
        } while (begin < end);
    }
    //在 connector 上进行同步发送
    void sync_write(const std::string &data, bool retry){
        if (!is_open()){
            return;
        }
        time_t time_now = time(0);
        if (m_sendbegin) {
            if (time_now - m_sendbegin > 10) {
                sync_close(false);
                return;
            }
        }
        if (retry == false){
            if (m_linger){
                return;
            }
            if (m_send.size()){
                m_circular_buffer->write(
                    data.c_str(), data.size()
                    );
                return;
            }
            m_send = std::move(data);
        }
        m_socket.async_send(
            asio::buffer(m_send.c_str(), m_send.size()),
            std::bind(&connector::w_handler
                , shared_from_this()
                , std::placeholders::_1
                , std::placeholders::_2
                )
            );
        m_sendbegin = time_now;
    }
    //在 connector 上执行同步关闭操作
    void sync_close(bool linger){
        asio::error_code ec;
        if (linger){
            if (m_send.size() || m_circular_buffer->used()){
                m_linger = linger;
                return;
            }
        }
        m_socket.close();
    }
    //io_read 事件的回调函数
    void r_handler(const asio::error_code &ec, size_t bytes){
        m_keepalive = time(0);
        if (!m_errno){
            inet_event inet_ev;
            inet_ev.type   = io_read;
            inet_ev.bytes  = bytes;
            inet_ev.buffer = m_recv;
            m_handler(ec.value(), inet_ev, shared_from_this());
            if (!ec){
                m_socket.async_receive(
                    asio::buffer(m_recv, sizeof(m_recv)),
                    std::bind(&connector::r_handler
                        , shared_from_this()
                        , std::placeholders::_1
                        , std::placeholders::_2
                    )
                );
            } else {
                m_errno = ec;
                sync_close(false);
                m_circular_buffer->clear();
                m_handler = [](int, const inet_event&, value_type){};
            }
        }
    }
    //io_write 事件的回调函数
    void w_handler(const asio::error_code &ec, size_t bytes){
        m_sendbegin = 0;
        if (!m_errno){ //没有发生过错误
            inet_event inet_ev;
            inet_ev.type   = io_write;
            inet_ev.bytes  = bytes;
            inet_ev.buffer = m_send.c_str();
            m_handler(ec.value(), inet_ev, shared_from_this());
            if (!ec){
                size_t rest = m_circular_buffer->used();
                if (rest){
                    rest = std::min<size_t>(
                        rest, ASIO_IO_WINDOW_SIZE
                        );
                    m_send.resize(rest);
                    m_circular_buffer->read((char*)m_send.c_str(), rest);
                    sync_write(m_send, true);
                    return;
                }
            } else {
                m_errno = ec;
                sync_close(false);
                m_circular_buffer->clear();
                m_handler = [](int, const inet_event&, value_type){};
            }
            m_send.clear();
            if (m_linger){ //延迟关闭
                sync_close(false); //立即关闭
            }
        }
    }
};
////////////////////////////////////////////////////////////////////////////////
//网络监听类
////////////////////////////////////////////////////////////////////////////////
class listener
    : public enable_shared_from_this<listener>{
    friend class connector;
public:
    typedef std::shared_ptr<
        listener
    > value_type;
public:
    //创建 listener 共享指针
    static value_type create(io::service::value_type ios){
        value_type s(new listener(ios));
        if (s && s->id() == 0)
            s.reset();
        return s;
    }
    //获得与 listener 关联的 io service 指针
    inline io::service::value_type get_io_service() const{
        return m_ios;
    }
    //获得 listener 上下文指针
    inline const void* get_context() const{
        return m_context;
    }
    //设置 listener 上下文指针
    inline void set_context(const void *context){
        m_context = context;
    }
    //获取 listener 的唯一标识符
    inline int id() const{
        return m_id;
    }
    //获取 listener 的监听类型
    inline style_type get_type() const{
        return m_type;
    }
    //获取 listener 监听的本地地址
    inline std::string get_local_name() const{
        return m_local.address().to_string();
    }
    //获取 listener 监听的本地端口
    inline unsigned short get_local_port() const{
        return m_local.port();
    }
    //判断 listener 是否处于 open 状态
    inline bool is_open() const{
        return m_acceptor.is_open();
    }
    //在本地创建一个 TCP 监听
    template<typename Handler>
    int bind(Handler handler, unsigned short port, int backlog = 5, const char *host = 0, bool reuseaddr = false, style_type type = tcpsocket){
        int result = bind(port, host, reuseaddr);
        if (result == ASIO_RESULT_OK){
            result = listen(handler, backlog);
        }
        console::log("%s(%d, %s), backlog=%d.\r\n",
            __FUNCTION__, port, host ? host : "0.0.0.0", backlog
            );
        return (m_type = type), result;
    }
#if defined(ASIO_ENABLE_OPENSSL)
    //在本地创建一个 TCP 监听(支持SSL)
    template<typename Handler>
    int bind(Handler handler, ssl::context &ctx, unsigned short port, int backlog = 5, const char *host = 0, bool reuseaddr = false, style_type type = tcpsocket){
        int result = bind(port, host, reuseaddr);
        if (result == ASIO_RESULT_OK){
            result = listen(handler, ctx, backlog);
        }
        console::log("%s(%d, %s), backlog=%d.\r\n",
            __FUNCTION__, port, host ? host : "0.0.0.0", backlog
        );
        return (m_type = type), result;
    }
#endif
    //关闭 listener 的本地监听
    virtual void close(int linger = 0){
        get_io_service()->post(
            std::bind(&listener::sync_close
                , shared_from_this()
                )
            );
    }
    //析构函数
    virtual ~listener(){
        asio::error_code ec;
        m_acceptor.close(ec);
        io::service::push_idle_id(m_id);
        console::log("%s is invoked.\r\n", __FUNCTION__);
    }
private:
    //默认构造函数
    inline listener(io::service::value_type ios)
        : m_context(0)
        , m_id(io::service::pop_next_id())
        , m_type(tcpsocket)
        , m_ios(ios)
        , m_acceptor(*ios)
#if defined(ASIO_ENABLE_OPENSSL)
        , m_ssl_ctx(0)
#endif
    {
        console::log("%s is invoked.\r\n", __FUNCTION__);
    }
    typedef std::function<void(
        listener::value_type, //监听器共享指针
        connector::value_type //连接器共享指针
    )> io_handler_callback;
private:
    const void*               m_context;
    const int                 m_id;
    style_type                m_type;
    io_handler_callback       m_handler;
    asio::ip::tcp::endpoint   m_local;
    io::service::value_type   m_ios;
    asio::ip::tcp::acceptor   m_acceptor;
#if defined(ASIO_ENABLE_OPENSSL)
    ssl::context*             m_ssl_ctx;
#endif
private:
    //在本地建立一个 TCP 监听
    int bind(unsigned short port, const char *host = 0, bool reuseaddr = false){
        asio::error_code ec;
        m_local.port(port);
        if (host){
            asio::ip::address addr(
                asio::ip::address::from_string(host, ec)
                );
            if (ec)
                return ec.value();
            m_local.address(addr);
        }
        m_acceptor.open(m_local.protocol(), ec);
        if (ec){
            return ec.value();
        }
        m_acceptor.set_option(
            asio::socket_base::reuse_address(reuseaddr),
            ec
            );
        if (ec){
            return ec.value();
        }
        m_acceptor.bind(m_local, ec);
        return ec.value();
    }
    //同步关闭网络监听
    void sync_close(){
        if (is_open()){
            asio::error_code error;
            m_acceptor.close(error);
        }
    }
    //网络事件回调函数
    void io_handler(const asio::error_code &ec, connector::value_type s){
        if (!is_open()){
            m_handler = [](
                value_type,
                connector::value_type
                ) {};
            return;
        }
        connector::value_type socket;
#if defined(ASIO_ENABLE_OPENSSL)
        if (m_ssl_ctx){
            socket = connector::create(get_io_service(), *m_ssl_ctx);
        }
#endif
        if (!socket){
            socket = connector::create(get_io_service());
        }
        if (!socket){
            s->close();
            socket = s;
        } else {
            if (ec){
                s->close();
            } else if (s->is_openssl()){
#if defined(ASIO_ENABLE_OPENSSL)
                s->m_socket.async_handshake(
                    std::bind(&listener::handshake, shared_from_this(), std::placeholders::_1, s)
                );
#endif
            } else {
                m_handler(shared_from_this(), s);
            }
        }
        async_accept(
            socket, std::bind(&listener::io_handler
                , shared_from_this()
                , std::placeholders::_1
                , socket
                )
            );
    }
    //在本地建立一个网络监听
    template<typename Handler>
    int listen(Handler handler, int backlog = 5){
        asio::error_code ec;
        m_acceptor.listen(backlog, ec);
        if (ec){
            return ec.value();
        }
        m_handler = handler;
        connector::value_type socket;
        socket = connector::create(get_io_service());
        if (!socket){
            return asio::error::no_memory;
        }
        async_accept(
            socket, std::bind(&listener::io_handler
                , shared_from_this()
                , std::placeholders::_1
                , socket
                )
            );
        return ec.value();
    }
#if defined(ASIO_ENABLE_OPENSSL)
    //SSL 握手回调函数
    void handshake(const asio::error_code& ec, connector::value_type s){
        if (ec) {
            s->close(false);
        } else if (m_handler){
            m_handler(shared_from_this(), s);
        }
    }
    template<typename Handler>
    int listen(Handler handler, ssl::context &ctx, int backlog = 5){
        asio::error_code ec;
        m_acceptor.listen(backlog, ec);
        if (ec){
            return ec.value();
        }
        m_ssl_ctx = &ctx;
        m_handler = handler;
        connector::value_type socket;
        socket = connector::create(get_io_service(), ctx);
        if (!socket){
            return asio::error::no_memory;
        }
        async_accept(
            socket, std::bind(&listener::io_handler
                , shared_from_this()
                , std::placeholders::_1
                , socket
            )
        );
        return ec.value();
    }
#endif
    template<typename Handler>
    void async_accept(connector::value_type s, Handler handler){
        s->m_initiator = false;
        m_acceptor.async_accept(s->m_socket.lowest_layer(), handler);
    }
};
////////////////////////////////////////////////////////////////////////////////
//网络封装类
////////////////////////////////////////////////////////////////////////////////
template<typename _Ty> class trigger
    : public std::enable_shared_from_this<_Ty>{
    io::service::value_type m_ios;
public:
    typedef std::shared_ptr<_Ty> value_type;
    virtual ~trigger(){
        stop();
    }
    //创建一个网络触发器共享指针
    static value_type create(){
        return value_type(new _Ty());
    }
    //获得网络触发器的 io service 指针
    inline io::service::value_type get_io_service() const{
        return m_ios;
    }
    //获取网络触发器的空闲时长
    inline size_t get_idle_time() const{
        return m_ios->get_idle_time();
    }
    //将一个已连接的 connector 绑定在触发器上
    inline int bind(connector::value_type s, style_type type = tcpsocket){
        return s->bind([&](int ec, const inet_event &ev, connector::value_type s){
            deliver(ec, ev, s);
        }, false, type);
    }
    //在本地建立一个 TCP 的网络监听并返回 listener 共享指针
    inline listener::value_type bind(unsigned short port, int backlog = 5, const char *host = 0, bool reuseaddr = false, style_type type = tcpsocket){
        listener::value_type acceptor;
        acceptor = listener::create(m_ios);
        if (acceptor){
            int result = acceptor->bind(
                [&](listener::value_type a, connector::value_type s){
                    bind(s, a->get_type());
                    on_accept(s, a);
                }, port, backlog, host, reuseaddr, type
            );
            if (result != 0){
                acceptor->close();
                acceptor.reset();
            }
        }
        return acceptor;
    }
#if defined(ASIO_ENABLE_OPENSSL)
    //在本地建立一个 SSL TCP 的网络监听并返回 listener 共享指针
    inline listener::value_type bind(ssl::context &ctx, unsigned short port, int backlog = 5, const char *host = 0, bool reuseaddr = false, style_type type = tcpsocket){
        listener::value_type acceptor;
        acceptor = listener::create(m_ios);
        if (acceptor){
            int result = acceptor->bind(
                [&](listener::value_type a, connector::value_type s){
                    bind(s, a->get_type());
                    on_accept(s, a);
                }, ctx, port, backlog, host, reuseaddr, type
            );
            if (result != 0){
                acceptor->close();
                acceptor.reset();
            }
        }
        return acceptor;
    }
#endif
    //给触发器发送一个异步消息以在未来去执行指定的处理函数
    template<typename Handler>
    inline void post(Handler handler){
        m_ios->post(handler);
    }
    //给触发器发送一个异步消息以在未来去执行指定的处理函数
    template<typename Handler>
    inline void post(Handler handler, unsigned int delay){
        m_ios->post(handler, delay);
    }
    //给触发器发送一个同步消息以执行指定的处理函数
    template<typename Handler>
    inline void dispatch(Handler handler){
        m_ios->dispatch(handler);
    }
    //运行当前触发器主消息循环(驱动消息泵)
    template<typename Handler>
    inline size_t run(Handler handler, size_t interval){
        return m_ios->run(handler, interval);
    }
    //运行当前触发器主消息循环(驱动消息泵)
    inline size_t run(size_t interval){
        return m_ios->run(
            std::bind(&trigger::on_update
                , this
                , std::placeholders::_1
            ), interval
        );
    }
    //运行当前触发器主消息循环(驱动消息泵)
    inline size_t run()     {return m_ios->run();}
    inline size_t run_one() {return m_ios->run_one();}
    inline size_t poll()    {return m_ios->poll();}
    inline size_t poll_one(){return m_ios->poll_one();}
    inline void   stop()    {return m_ios->stop();}
    inline void   reset()   {m_ios->reset();}
    inline bool   stopped() const {return m_ios->stopped();}
protected:
    inline trigger(const trigger&){}
    inline trigger(){m_ios = io::service::create();}
    virtual bool handshake(ip::tcp::connector::value_type s){
        return true;
    }
protected:
    virtual void on_update   (int delta){}
    virtual void on_handshake(ip::tcp::connector::value_type s){}
    virtual void on_accept   (ip::tcp::connector::value_type s, ip::tcp::listener::value_type a){}
    virtual void on_error    (ip::tcp::connector::value_type s, int, ip::tcp::event_type t){}
    virtual void on_send     (ip::tcp::connector::value_type s, const std::string& d){}
    virtual void on_request  (ip::tcp::connector::value_type s, const std::string& d) {}
    virtual void on_receive  (ip::tcp::connector::value_type s, const std::string& d) {}
private:
    //接受一个来自对端的 Websocket 握手请求
    void wsp_accept(connector::value_type s){
        http::response head;
        http::request &req = s->get_request();
        bool handshake_ok = handshake(s);
        head.status = handshake_ok ? "101" : "403";
        head.result = handshake_ok ? "Switching Protocols" : "Forbidden";
        head.http_version_major = req.http_version_major;
        head.http_version_minor = req.http_version_minor;
        head.add_header("Pragma", "no-cache");
        head.add_header("Cache-Control", "no-cache");
        head.add_header("Connection", handshake_ok ? "Upgrade" : "Close");
        //读取和设置 host 字段
        std::string host = req.get_header("Host");
        if (!host.empty()) {
            size_t pos = host.find(':');
            if (pos != std::string::npos) {
                host = host.substr(0, pos);
            }
            head.add_header("Server", host);
        }
        //如果允许连接
        if (handshake_ok) {
            if (!host.empty()) {
                std::string cookie1 = req.get_header("Cookie");
                std::string cookie2 = s->get_cookie();
                if (cookie1 != cookie2 && !cookie2.empty()) {
                    cookie1 = cookie2;
                    cookie1 += ";Path=/";
                    cookie1 += ";Domain=";
                    cookie1 += host;
                    head.add_header("Set-Cookie", cookie1);
                }
            }
            head.add_header("Upgrade", "Websocket");
            head.add_header("Sec-WebSocket-Accept", req.get_wsakey());
            std::string prol;
            prol = req.get_header("Sec-WebSocket-Protocol");
            if (!prol.empty()) {
                size_t pos = prol.find(' ');
                if (pos != std::string::npos) {
                    prol = prol.substr(pos, 0);
                }
                head.add_header("Sec-WebSocket-Protocol", prol);
            }
            //跨域允许
            std::string origin = req.get_header("Origin");
            if (!origin.empty()) {
                head.add_header("Access-Control-Allow-Credentials", "true");
                head.add_header("Access-Control-Allow-Origin", origin);
            }
        }
        s->write(head.to_string(), WSP_TYPE_TEXT);
        if (handshake_ok) {
            s->set_wsp_ready();
            on_handshake(s); //调用握手成功回调函数
        } else {
            s->close(false); //关闭当前连接
        }
    }
    //接受一个来自对端的 Websocket 握手应答
    void wsp_verify(const std::string &data, connector::value_type s){
        http::response response;
        http::response_parser response_parser;
        const char *begin = data.c_str();
        const char *end = begin + data.size();
        http::response_parser::result_type result;
        if (begin < end) {
            std::tie(result, begin) = response_parser.parse(
                response,
                begin,
                end
            );
            switch (result) {
            case http::request_parser::bad:
                s->close(false);
            case http::request_parser::indeterminate:
                return;
            }
            //判断返回状态值
            if (response.status != "101") {
                s->close(false);
                return;
            }
            //设置各种标记
            s->set_wsp_ready();
            s->get_request().upgrade = true;
            s->get_request().handshaked = true;
            on_handshake(s);
        }
        if (begin < end){
            wsp_parse(std::string(begin, (end - begin)), s);
        }
    }
    //解析收到的 Websocket 数据包并缓存
    void wsp_parse(const std::string &data, connector::value_type s){
        const char *begin = data.c_str();
        const char *end   = begin + data.size();
        auto &packet = s->get_request().wsp;
        http::wsp_parser::result_type result;
        while (begin < end){
            std::tie(result, begin) = s->get_wsp_parser().parse(
                s->get_request(),
                begin,
                end,
                s->get_limit()
                );
            switch (result){
            case http::request_parser::bad:
                s->close(false);
            case http::request_parser::indeterminate:
                return;
            }
            int type = packet.type();
            if (WSP_TYPE_RESERVED(type)){
                continue;
            }
            if (type == WSP_TYPE_PONG){
                continue;
            }
            if (type == WSP_TYPE_PING){
                s->write(0, 0, WSP_TYPE_PONG);
                continue;
            }
            if (type == WSP_TYPE_CLOSE){
                s->write(0, 0, WSP_TYPE_CLOSE);
                s->close(true);
                return;
            }
            if (type == WSP_TYPE_TEXT){
                if (!is_utf8(packet.data())){
                    s->close();
                    return;
                }
            }
            on_receive(
                s, std::string(packet.data(), packet.size())
            );
        }
    }
    //根据不同的连接类型进行数据回调的分发处理
    void deliver(const std::string &data, connector::value_type s){
        style_type type = s->get_type();
        //如果不是 websocket 则直接处理
        if (type != websocket){
            on_receive(s, data);
            return;
        }
        http::request &request = s->get_request();
        //如果 http 握手完毕了
        if (request.is_handshake()){
            if (request.is_wsp()){
                wsp_parse(data, s);
                return;
            }
            request.clear();
        }
        //如果是连接的主动发起者
        else if (s->is_initiator()){
            wsp_verify(data, s);
            return;
        }
        //解析 http 请求头数据
        const char *begin = data.c_str();
        const char *end = begin + data.size();
        http::request_parser::result_type result;
        while (begin < end){
            std::tie(result, begin) = s->get_parser().parse(
                request,
                begin,
                end,
                s->get_limit()
            );
            //判断解析结果
            switch (result){
            case http::request_parser::bad:
                s->close(false);
            case http::request_parser::indeterminate:
                return;
            }
            if (!request.is_wsp()){
                on_request(s, request.data);
            } else if (request.method != "GET"){
                s->close(false);
                return;
            } else {
                wsp_accept(s);
            }
        }
    }
    //处理网络事件并派发给对应的处理回调函数
    void deliver(int ec, const inet_event &ev, connector::value_type s){
        if (!ec){
            std::string packet;
            if (ev.buffer && ev.bytes){
                packet.append(ev.buffer, ev.bytes);
            }
            int events = s->get_events() & ev.type;
            switch (events){
            case io_read:  deliver(packet, s);
                break;
            case io_write: on_send(s, packet);
                break;
            }
        } else {
            on_error(s, ec, ev.type); //io error occurs.
        }
    }
};
////////////////////////////////////////////////////////////////////////////////
} //End of namespace tcp
////////////////////////////////////////////////////////////////////////////////
} //End of namespace ip
////////////////////////////////////////////////////////////////////////////////
#endif //__ASIO_PLUSPLUS_INCLUDED_H_
